#include "can_test.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include <string.h>

static WHT_CAN_Message_t WHT_CAN_Rx_Message[12];
static SemaphoreHandle_t Rx_xSemaphore;

static void WHT_CAN_Rx_IT_Callback(unsigned int id, unsigned char *const buffer, unsigned char length);


static void WHT_CAN_Rx_IT_Callback(unsigned int id, unsigned char *const buffer, unsigned char length)
{
    static uint8_t Pos = 0;
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    if (WHT_CAN_Rx_Message[Pos].state == DISABLE)
    {
        memcpy(WHT_CAN_Rx_Message[Pos].buffer, buffer, length);
        WHT_CAN_Rx_Message[Pos].length = length;
        WHT_CAN_Rx_Message[Pos].ID = id;
        WHT_CAN_Rx_Message[Pos].state = ENABLE;
        Pos = (Pos + 1) % (sizeof(WHT_CAN_Rx_Message) / sizeof(WHT_CAN_Rx_Message[0]));
    }

    xSemaphoreGiveFromISR(Rx_xSemaphore, &xHigherPriorityTaskWoken);//释放信号量
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

/* 处理完接收的数据必须要清除标志位 */
WHT_CAN_Message_t* WHT_CAN_Receive_Message(uint32_t timeout_ms)
{
    static uint8_t Pos = 0;
    WHT_CAN_Message_t*  Message;

    Message = &WHT_CAN_Rx_Message[Pos];

    if (Message->state == ENABLE)
    {
        xSemaphoreTake(Rx_xSemaphore, 0);
        Pos = (Pos + 1) % (sizeof(WHT_CAN_Rx_Message) / sizeof(WHT_CAN_Rx_Message[0]));
        return Message;
    }
    else if (xSemaphoreTake(Rx_xSemaphore, pdMS_TO_TICKS(timeout_ms)) == pdTRUE)
    {
        
        return WHT_CAN_Receive_Message(0);
    }
    
    return NULL;
}

int WHT_CAN_Send_Message(WHT_CAN_Message_t* message, uint32_t timeout_ms)
{
    TickType_t xTicksToDelay;

    if (message->length > sizeof(message->buffer))
    {
        return -2;
    }
    
    xTicksToDelay = pdMS_TO_TICKS(timeout_ms);
    while (WHT_CAN_BSP.WHT_CAN1_Info->TRx_State == CAN_TRx_Busy)
    {
        if (xTicksToDelay > 0)
        {
            xTicksToDelay--;
            vTaskDelay(1);
        }
        else
        {
            return -3;
        }
    }

    if (WHT_CAN_BSP.WHT_TxMessage(CAN_1, message, timeout_ms) == ERROR)
    {
        printf("WHT_CAN_Send_Message Error\r\n");
        return -1;
    }
    
    return 0;
}


void WHT_CAN_Init(void)
{
    WHT_CAN_Config_t WHT_CAN_Config;

    WHT_CAN_Config.ID = Device_CAN_ID;
    WHT_CAN_Config.PreemptionPriority = 15;
    WHT_CAN_Config.SubPriority = 0;
    WHT_CAN_Config.Rx_IT_Callback = WHT_CAN_Rx_IT_Callback;
    WHT_CAN_Config.prescaler = 16;

    Rx_xSemaphore = xSemaphoreCreateBinary();
    WHT_CAN_BSP.WHT_Config(CAN_1, &WHT_CAN_Config);
    printf("WHT_CAN_Init OK\r\n");
}
